#pragma once

#include <iostream>
#include <string>
#include <list>
#include <memory>
#include <sys/types.h>
#include <sys/socket.h>
#include <algorithm>

#include "InetAddr.hpp"
#include "Log.hpp"
#include "Mutex.hpp"

using namespace LogModule;
using namespace LockModule;

class UserInterface
{
public:
    virtual ~UserInterface() = default;
    virtual void SendTo(int sockfd, const std::string &message) = 0;
    virtual bool operator ==(const InetAddr &u) = 0;
    virtual std::string Id() = 0;
};


class User : public UserInterface
{
public:
    User(const InetAddr &id): _id(id)
    {
    }
    void SendTo(int sockfd, const std::string &message) override
    {
        LOG(LogLevel::DEBUG) << "send message to " << _id.Addr() << ", info: " << message;
        int n = ::sendto(sockfd, message.c_str(), message.size(), 0, _id.NetAddr(), _id.NetAddrLen());
        (void)n;
    }
    bool operator ==(const InetAddr &u) override
    {
        return _id == u;
    }
    std::string Id() override
    {
        return _id.Addr();
    }
    ~User()
    {}
private:
    InetAddr _id;
};


// 对用户消息进行路由
// UserManage 把所有用户先管理起来

// 把一个新用户添加到在线用户列表，一旦要发信息，我们的 UserManage 不做发送，他要调的就是 User 提供的公共方法
// 这种设计模式就称为 观察者模式 -> observer

class UserManage
{
public:
    UserManage()
    {
    }

    void AddUser(InetAddr &id)
    {
        LockGuard lockguard(_mutex);
        for(auto &user: _online_user)
        {
            if(*user == id)
            {
                LOG(LogLevel::INFO) << id.Addr() << " 这个用户已经存在";
                return ;
            }
        }
        
        LOG(LogLevel::INFO) << "新增该用户: " << id.Addr();
        _online_user.push_back(std::make_shared<User>(id)); // 构建 User 对象
        PrintUser();
    }
    void DelUser(InetAddr &id)
    {
        // 写法 1
        auto pos = std::remove_if(_online_user.begin(), _online_user.end(), [&id](std::shared_ptr<UserInterface> &user){
            return *user == id;
        });
        _online_user.erase(pos, _online_user.end());
        PrintUser();

        // // 写法 2 -- 不对
        // for(auto &user : _online_user)
        // {
        //     if(*user == id){
        //         _online_user.erase(user);
        //         break; // 必须 break，避免迭代器失效问题
        //     }
        // }
        // 在基于范围的 for 循环中，迭代器是隐式管理的。
        // 当调用 erase 后，迭代器 user 失效，但循环仍然尝试继续使用它（即使你使用了 break，某些编译器或情况下仍可能导致问题）。

        // // 写法 3
        // for (auto it = _online_user.begin(); it != _online_user.end(); ) {
        //     if (**it == id) {
        //         it = _online_user.erase(it); // erase 返回下一个有效的迭代器
        //     } else {
        //         ++it; // 继续遍历
        //     }
        // }
    }

    void Router(int sockfd, const std::string &message) // 消息转发
    {
        LockGuard lockguard(_mutex);
        for(auto &user : _online_user)
        {
            user->SendTo(sockfd, message);
        }
    }

    void PrintUser()
    {
        for(auto user : _online_user)
        {
            LOG(LogLevel::DEBUG) << "在线用户->" << user->Id();
        }
    }

    ~UserManage()
    {}

private:
    std::list<std::shared_ptr<UserInterface>> _online_user; // 在线用户
    Mutex _mutex;
};